Specify the tissue of interest, run the boilerplate code which sets up the functions and environment, load the tissue object.

tissue_of_interest = "Marrow"
library(here)
here() starts at /Users/olgabot/code/tabula-muris
source(here("00_data_ingest", "02_tissue_analysis_rmd", "boilerplate.R"))
Loading required package: ggplot2
Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:ggplot2’:

    ggsave

Loading required package: Matrix
tiss = load_tissue_facs(tissue_of_interest)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Scaling data matrix"

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |====                                                                                        |   4%
  |                                                                                                  
  |========                                                                                    |   8%
  |                                                                                                  
  |============                                                                                |  12%
  |                                                                                                  
  |===============                                                                             |  17%
  |                                                                                                  
  |===================                                                                         |  21%
  |                                                                                                  
  |=======================                                                                     |  25%
  |                                                                                                  
  |===========================                                                                 |  29%
  |                                                                                                  
  |===============================                                                             |  33%
  |                                                                                                  
  |==================================                                                          |  38%
  |                                                                                                  
  |======================================                                                      |  42%
  |                                                                                                  
  |==========================================                                                  |  46%
  |                                                                                                  
  |==============================================                                              |  50%
  |                                                                                                  
  |==================================================                                          |  54%
  |                                                                                                  
  |======================================================                                      |  58%
  |                                                                                                  
  |==========================================================                                  |  62%
  |                                                                                                  
  |=============================================================                               |  67%
  |                                                                                                  
  |=================================================================                           |  71%
  |                                                                                                  
  |=====================================================================                       |  75%
  |                                                                                                  
  |=========================================================================                   |  79%
  |                                                                                                  
  |=============================================================================               |  83%
  |                                                                                                  
  |================================================================================            |  88%
  |                                                                                                  
  |====================================================================================        |  92%
  |                                                                                                  
  |========================================================================================    |  96%
  |                                                                                                  
  |============================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Visualize top genes in principal components

Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.

PCElbowPlot(object = tiss)

Choose the number of principal components to use.

# Set number of principal components. 
n.pcs = 18

The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale…higher resolution will give more clusters, lower resolution will give fewer.

For the top-level clustering, aim to under-cluster instead of over-cluster. It will be easy to subset groups and further analyze them below.

# Set resolution 
res.used <- 0.5
tiss <- FindClusters(object = tiss, reduction.type = "pca", dims.use = 1:n.pcs, 
    resolution = res.used, print.output = 0, save.SNN = TRUE)

To visualize

# If cells are too spread out, you can raise the perplexity. If you have few cells, try a lower perplexity (but never less than 10).
tiss <- RunTSNE(object = tiss, dims.use = 1:n.pcs, seed.use = 10, perplexity=84)
# note that you can set do.label=T to help label individual clusters
TSNEPlot(object = tiss, do.label = T)

Compare to previous annotations

method = "facs"
tiss = compare_previous_annotation(tiss, tissue_of_interest, method, filename = here('00_data_ingest', '03_tissue_annotation_csv', 
                    paste0(tissue_of_interest, "_", method, "_annotation_rahul.csv")))

                        Cd3e+_Klrb1+ B cell                  common lymphoid progenitor 
                                         37                                         129 
                      Dntt- late pro-B cell                       Dntt+ late pro-B cell 
                                        203                                          92 
       granulocyte monocyte progenitor cell   hematopoietic stem cell enriched fraction 
                                         65                                          50 
                      HSC enriched fraction                immature natural killer cell 
                                        158                                          31 
                         immature NK T cell                             immature T cell 
                                         46                                          53 
                                  MAA001844                  mature natural killer cell 
                                        194                                          54 
    megakaryocyte-erythroid progenitor cell                                          NA 
                                         46                                         140 
                    pre-natural killer cell                           regulatory T cell 
                                         19                                          32 
Slamf1-negative multipotent progenitor cell Slamf1-positive multipotent progenitor cell 
                                        548                                          89 
                                             
                                                0   1   2   3   4   5   6   7   8   9  10  11  12
  Cd3e+_Klrb1+ B cell                           0   0   0   0   0   0   0   0   0   0   0  33   4
  common lymphoid progenitor                  127   0   0   0   2   0   0   0   0   0   0   0   0
  Dntt- late pro-B cell                         0   0   0   0   0   0   0   0 203   0   0   0   0
  Dntt+ late pro-B cell                         0   0   0   0   0   0   0   0  92   0   0   0   0
  granulocyte monocyte progenitor cell         62   0   0   0   3   0   0   0   0   0   0   0   0
  hematopoietic stem cell enriched fraction    45   0   0   0   5   0   0   0   0   0   0   0   0
  HSC enriched fraction                        93   0   0   0  65   0   0   0   0   0   0   0   0
  immature natural killer cell                  0   0   0   0   0   0   0   0   0   0   0   2  29
  immature NK T cell                            0   0   0   0   0   0   0   0   0   0   0  45   1
  immature T cell                               0   0   0   0   0   0   0   0   0   0   0  53   0
  MAA001844                                     0   0   0   0 194   0   0   0   0   0   0   0   0
  mature natural killer cell                    0   0   0   0   0   0   0   0   0   0   0   2  52
  megakaryocyte-erythroid progenitor cell      46   0   0   0   0   0   0   0   0   0   0   0   0
  NA                                          106   0   0   0   0   2   0  11   6  11   0   2   2
  pre-natural killer cell                       0   0   0   0   0   0   0   0   0   0   0   3  16
  regulatory T cell                             0   0   0   0   0   0   0   0   0   0   0  32   0
  Slamf1-negative multipotent progenitor cell 446   0   0   0 102   0   0   0   0   0   0   0   0
  Slamf1-positive multipotent progenitor cell  89   0   0   0   0   0   0   0   0   0   0   0   0

                            basophil                          granulocyte 
                                  24                                  758 
granulocyte monocyte progenitor cell              granulocytopoietic cell 
                                 134                                  211 
                     immature B cell                           macrophage 
                                 365                                  174 
                            monocyte                                   NA 
                                 257                                  140 
                        naive B cell                           pre-B cell 
                                 676                                  517 
                                      
                                         0   1   2   3   4   5   6   7   8   9  10  11  12
  basophil                               0   0   0   0   0   0   0   0   0   0   0   0  24
  granulocyte                            0   0   0 390   0 368   0   0   0   0   0   0   0
  granulocyte monocyte progenitor cell  62   0   0   0   3   0   0  69   0   0   0   0   0
  granulocytopoietic cell                0   0   0   0   0   1   0   0   0 210   0   0   0
  immature B cell                        0  21   3   0   0   0 341   0   0   0   0   0   0
  macrophage                             0   0   0   0   1   0   0   0   0   0 173   0   0
  monocyte                               1   0   0   0   0   0   0 256   0   0   0   0   0
  NA                                   106   0   0   0   0   2   0  11   6  11   0   2   2
  naive B cell                           0 676   0   0   0   0   0   0   0   0   0   0   0
  pre-B cell                             0   0 514   0   0   0   3   0   0   0   0   0   0
TSNEPlot(object = tiss, do.return = TRUE, group.by = "previous_cell_ontology_class")

TSNEPlot(object = tiss, do.return = TRUE, group.by = "previous_free_annotation")

Check expression of genes of interset.

Dotplots let you see the intensity of exppression and the fraction of cells expressing for each of your genes of interest.

How big are the clusters?

table(tiss@ident)

   0    1    2    3    4    5    6    7    8    9   10   11   12 
1015  697  517  390  372  371  344  336  301  221  173  172  128 

Assigning cell type identity to clusters

At a coarse level, we can use canonical markers to match the unbiased clustering to known cell types:

previous_annotation_table(tiss)
[1] "previous_free_annotation"
                                             
                                                0   1   2   3   4   5   6   7   8   9  10  11  12
  Cd3e+_Klrb1+ B cell                           0   0   0   0   0   0   0   0   0   0   0  33   4
  common lymphoid progenitor                  127   0   0   0   2   0   0   0   0   0   0   0   0
  Dntt- late pro-B cell                         0   0   0   0   0   0   0   0 203   0   0   0   0
  Dntt+ late pro-B cell                         0   0   0   0   0   0   0   0  92   0   0   0   0
  granulocyte monocyte progenitor cell         62   0   0   0   3   0   0   0   0   0   0   0   0
  hematopoietic stem cell enriched fraction    45   0   0   0   5   0   0   0   0   0   0   0   0
  HSC enriched fraction                        93   0   0   0  65   0   0   0   0   0   0   0   0
  immature natural killer cell                  0   0   0   0   0   0   0   0   0   0   0   2  29
  immature NK T cell                            0   0   0   0   0   0   0   0   0   0   0  45   1
  immature T cell                               0   0   0   0   0   0   0   0   0   0   0  53   0
  MAA001844                                     0   0   0   0 194   0   0   0   0   0   0   0   0
  mature natural killer cell                    0   0   0   0   0   0   0   0   0   0   0   2  52
  megakaryocyte-erythroid progenitor cell      46   0   0   0   0   0   0   0   0   0   0   0   0
  NA                                          106   0   0   0   0   2   0  11   6  11   0   2   2
  pre-natural killer cell                       0   0   0   0   0   0   0   0   0   0   0   3  16
  regulatory T cell                             0   0   0   0   0   0   0   0   0   0   0  32   0
  Slamf1-negative multipotent progenitor cell 446   0   0   0 102   0   0   0   0   0   0   0   0
  Slamf1-positive multipotent progenitor cell  89   0   0   0   0   0   0   0   0   0   0   0   0
[1] "previous_cell_ontology_class"
                                      
                                         0   1   2   3   4   5   6   7   8   9  10  11  12
  basophil                               0   0   0   0   0   0   0   0   0   0   0   0  24
  granulocyte                            0   0   0 390   0 368   0   0   0   0   0   0   0
  granulocyte monocyte progenitor cell  62   0   0   0   3   0   0  69   0   0   0   0   0
  granulocytopoietic cell                0   0   0   0   0   1   0   0   0 210   0   0   0
  immature B cell                        0  21   3   0   0   0 341   0   0   0   0   0   0
  macrophage                             0   0   0   0   1   0   0   0   0   0 173   0   0
  monocyte                               1   0   0   0   0   0   0 256   0   0   0   0   0
  NA                                   106   0   0   0   0   2   0  11   6  11   0   2   2
  naive B cell                           0 676   0   0   0   0   0   0   0   0   0   0   0
  pre-B cell                             0   0 514   0   0   0   3   0   0   0   0   0   0
# stash current cluster IDs
tiss <- StashIdent(object = tiss, save.name = "cluster.ids")
# enumerate current cluster IDs and the labels for them
cluster.ids <- c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
free_annotation <- c(NA, NA, "pre-B cell (Philadelphia nomenclature)",
                     NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)
cell_ontology_class <-c(
  NA, # Cluster 0 is a mix of progenitors and precursors
  "naive B cell", 
  "precursor B cell", 
  "granulocyte", 
  "hematopoietic precursor cell", 
  "granulocyte",
  "immature B cell", 
  NA, # Cluster 7 is a mix of monocytes and granulocyte progenitors
  "late pro-B cell", 
  "granulocytopoietic cell",
  "macrophage",
  NA, # Cluster 11 is a mix of T, NKT and B cells
  NA # Cluster 12 is a mix of basophil, B cells, immature NK cells, mature NK cells, pre-natural killer cells
)
tiss = stash_annotations(tiss, cluster.ids, free_annotation, cell_ontology_class)
data.frame(cluster.ids, cell_ontology_class, free_annotation)
TSNEPlot(object = tiss, do.label = TRUE, pt.size = 0.5, group.by='cell_ontology_class')

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = tiss, do.return = TRUE, group.by = "plate.barcode")

Print a table showing the count of cells in each identity category from each plate.

table(as.character(tiss@ident), as.character(tiss@meta.data$plate.barcode))
    
     D041912 D042044 D042193 D042467 D042479 D045139 D045140 MAA000409 MAA000596 MAA000600 MAA000639
  0        1       0       2       1       0       0       0         0       290       333         0
  1        2      89      96      39      53       0       0         2         1         5         0
  10       2      31       2       1      15       0       0         0         0         0         0
  11       0       0      50      20       2       0       0         0         0         0         0
  12       6       0      33      19       1       3       2         1         0         0         0
  2        0      53      45      16      59       0       0         0         0         0         0
  3       68       2       3       2       1      29      84       132         0         0        62
  4        0       0       0       0       0       0       2         0         0         1         0
  5       75       0       2       1       0      38      59        75         0         0       116
  6        0      42      48      18      33       0       0         0         1         0         0
  7       49       1       8       4       3      45      68        50         0         0        45
  8        0      89       7       3      82       0       0         0         0         0         0
  9       69       0       2       0       0      14      16        62         0         0        50
    
     MAA000652 MAA000844 MAA000848 MAA001842 MAA001844 MAA001883 MAA001884 MAA001887 MAA001888
  0          0         1       346         0         3         0         0        38         0
  1         52        67         2        38         7        38       171         5        30
  10        38         9         0         1         0        26        37         0        11
  11         0        47         0         1         2         1         2         1        46
  12         0        23         0         3         1         1         0         2        33
  2        122        62         0         4         0       104        49         0         3
  3          2         5         0         0         0         0         0         0         0
  4          0         0         3         0       190         0         1       174         1
  5          2         2         0         0         0         0         0         0         1
  6         36        42         0         5         2        45        64         3         5
  7          0         8         0         2        28         0         0        17         8
  8         46         5         0         1         1        33        26         7         1
  9          1         2         0         0         3         0         0         2         0

Redo Subcluster as per the code from pancreas plate Rmd, which is without regressing out ribosomal genes

Subset A == T_NK_NKT cell (Clusters 11, 12)

subtissA = SubsetData(tiss, ident.use = c(11, 12))
subtissA <- subtissA %>% ScaleData() %>% 
  FindVariableGenes(do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
  RunPCA(do.print = FALSE)
[1] "Scaling data matrix"

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |============================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

PCHeatmap(object = subtissA, pc.use = 1:3, cells.use = 100, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)

PCElbowPlot(subtissA)

sub.n.pcs = 4
sub.res.use = 1
subtissA <- subtissA %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.use, print.output = 0, save.SNN = TRUE) %>%
    RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=44)
TSNEPlot(object = subtissA, do.label = T, pt.size = 1.2, label.size = 4)

Check expression of genes of interset.

{r} # subtissA.markers <- FindAllMarkers(object = subtissA, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25) #

{r} # subtissA.markers %>% group_by(cluster) %>% top_n(6, avg_logFC) #

TSNEPlot(object = subtissA, do.return = TRUE, group.by = "previous_cell_ontology_class")

TSNEPlot(object = subtissA, do.return = TRUE, group.by = "previous_free_annotation")

previous_annotation_table(subtissA)
[1] "previous_free_annotation"
                              
                                0  1  2  3  4  5  6
  Cd3e+_Klrb1+ B cell           0  0 37  0  0  0  0
  immature natural killer cell  0  0  0  0 31  0  0
  immature NK T cell            1  0  6 36  3  0  0
  immature T cell              50  0  0  3  0  0  0
  mature natural killer cell    0 48  2  0  3  1  0
  NA                            0  0  0  1  0  0  3
  pre-natural killer cell       0  0  0  0  0  0 19
  regulatory T cell            31  0  0  1  0  0  0
[1] "previous_cell_ontology_class"
          
            0  1  2  3  4  5  6
  basophil  0  0  0  0  0 24  0
  NA        0  0  0  1  0  0  3

The multitude of clusters of each type correspond mostly to individual animals/sexes.

table(FetchData(subtissA, c('mouse.id','ident')) %>% droplevels())
        ident
mouse.id  0  1  2  3  4  5  6
  3_10_M 27  8  7 10  9  4  6
  3_38_F  1  0  3  1  5  1  0
  3_39_F 12  8 13 21 15 11  7
  3_8_M  30 18 16  8  7  5  8
  3_9_M  12 14  6  1  1  4  1
sub.cluster.ids <- c(0, 1, 2, 3, 4, 5, 6)
sub.free_annotation <- c("regulatory and immature T cell", NA, "Cd3e+ Klrb1+ B cell",  NA, NA, NA, NA)
""
[1] ""
sub.cell_ontology_class <-c("T cell", "mature natural killer cell","B cell",  "immature NK T cell", "immature natural killer cell", "basophil",  "pre-natural killer cell")
subtissA = stash_annotations(subtissA, sub.cluster.ids, sub.free_annotation, sub.cell_ontology_class)
tiss = stash_subtiss_in_tiss(tiss, subtissA)
head(tiss@meta.data)
data.frame(sub.cluster.ids, sub.cell_ontology_class, sub.free_annotation)

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = subtissA, do.return = TRUE, group.by = "plate.barcode")

Final coloring

Color by cell ontology class on the original TSNE.

TSNEPlot(object = subtissA, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

TSNEPlot(object = subtissA, do.label = TRUE, do.return = TRUE, group.by = "free_annotation")

Subset B == regulatory_immature T cell (Cluster 0)

Multiple cell-types in the cluster 0 of subtiss (original cluster 7)

subcluster the cluster 0 (regulatory_immature T cell) of subtiss (original cluster 7)

subtissB = SubsetData(subtissA, ident.use = c(0))
subtissB <- subtissB %>% ScaleData() %>% 
  FindVariableGenes(do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
  RunPCA(do.print = FALSE)
[1] "Scaling data matrix"

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |============================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

PCHeatmap(object = subtissB, pc.use = 1:3, cells.use = 150, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)

PCElbowPlot(subtissB)

sub.n.pcs = 3
sub.res.use = 1
subtissB <- subtissB %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.use, print.output = 0, save.SNN = TRUE) %>%
    RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=12)
TSNEPlot(object = subtissB, do.label = T, pt.size = 1.2, label.size = 4)

previous_annotation_table(subtissB)
[1] "previous_free_annotation"
                    
                      0  1  2
  immature NK T cell  0  0  1
  immature T cell    39  1 10
  regulatory T cell   1 25  5
[1] "previous_cell_ontology_class"
< table of extent 0 x 3 >

Check expression of genes of interset.

{r} # subtissB.markers <- FindAllMarkers(object = subtissB, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25) #

{r} # subtissB.markers %>% group_by(cluster) %>% top_n(6, avg_logFC) #

From these genes, it appears that the clusters represent:

The multitude of clusters of each type correspond mostly to individual animals/sexes.

table(FetchData(subtissB, c('mouse.id','ident')) %>% droplevels())
        ident
mouse.id  0  1  2
  3_10_M 10  9  8
  3_38_F  1  0  0
  3_39_F  0  9  3
  3_8_M  23  5  2
  3_9_M   6  3  3
previous_annotation_table(subtissB)
[1] "previous_free_annotation"
                    
                      0  1  2
  immature NK T cell  0  0  1
  immature T cell    39  1 10
  regulatory T cell   1 25  5
[1] "previous_cell_ontology_class"
< table of extent 0 x 3 >
sub.cluster.ids <- c(0, 1, 2)
sub.free_annotation <-c(NA, NA, NA)
sub.cell_ontology_class <-c("immature T cell", "regulatory T cell", "immature T cell")
subtissB = stash_annotations(subtissB, sub.cluster.ids, sub.free_annotation, sub.cell_ontology_class)
tiss = stash_subtiss_in_tiss(tiss, subtissB)
data.frame(sub.cluster.ids, sub.cell_ontology_class, sub.free_annotation)

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = subtissB, do.return = TRUE, group.by = "plate.barcode")

Final coloring

Color by cell ontology class on the original TSNE.

TSNEPlot(object = subtissB, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

Subset C == late pro-B cell (Cluster 8)

late pro-B cells are reportedly committed to B cell lineage as they begin expressing Pax5. They also have Rag1, Rag2, and Dntt expression. At single cell resolution there seem to be two subsets of late pro-B cells: Dntt+ and Dntt-.

It appears there are multiple novel cell-types within the Pax5+ late pro-B cell

subtissC = SubsetData(tiss, ident.use = c(8))
subtissC <- subtissC %>% ScaleData() %>% 
  FindVariableGenes(do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
  RunPCA(do.print = FALSE)
[1] "Scaling data matrix"

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |============================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

PCHeatmap(object = subtissC, pc.use = 1:3, cells.use = 500, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)

PCElbowPlot(subtissC)

sub.n.pcs = 4
sub.res.use = 1
subtissC <- subtissC %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.use, print.output = 0, save.SNN = TRUE) %>%
    RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=42)
TSNEPlot(object = subtissC, do.label = T, pt.size = 1.2, label.size = 4)

previous_annotation_table(subtissC)
[1] "previous_free_annotation"
                       
                         0  1  2  3  4
  Dntt- late pro-B cell 85 55 63  0  0
  Dntt+ late pro-B cell  1 15  0 44 32
  NA                     0  2  1  3  0
[1] "previous_cell_ontology_class"
    
     0 1 2 3 4
  NA 0 2 1 3 0

Check expression of genes of interset.

{r} # subtissC.markers <- FindAllMarkers(object = subtissC, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25) #

{r} # subtissC.markers %>% group_by(cluster) %>% top_n(6, avg_logFC) #

genes_to_check = c('Dntt')
# FeaturePlot(subtissC, genes_to_check, pt.size = 1, nCol = 3)
DotPlot(subtissC, genes_to_check, col.max = 2.5, plot.legend = T, do.return = T) + coord_flip()

The multitude of clusters of each type correspond mostly to individual animals/sexes.

table(FetchData(subtissC, c('mouse.id','ident')) %>% droplevels())
        ident
mouse.id  0  1  2  3  4
  3_10_M 24  3 17  4  3
  3_38_F  9  2  7  2  8
  3_39_F 11  9  4 14  3
  3_8_M  16 25 22 19  7
  3_9_M  26 33 14  8 11
sub.cluster.ids <- c(0, 1, 2, 3, 4)
sub.free_annotation <-
  c(
  "Dntt- late pro-B cell",
  "Dntt- late pro-B cell",
  "Dntt- late pro-B cell",
  "Dntt+ late pro-B cell",
  "Dntt+ late pro-B cell"
  )
  
  sub.cell_ontology_class <-
  c(
  "late pro-B cell",
  "late pro-B cell",
  "late pro-B cell",
  "late pro-B cell",
  "late pro-B cell"
  )
  
subtissC = stash_annotations(subtissC, sub.cluster.ids, sub.free_annotation, sub.cell_ontology_class)
tiss = stash_subtiss_in_tiss(tiss, subtissC)
data.frame(sub.cluster.ids, sub.cell_ontology_class, sub.free_annotation)
head(tiss@meta.data)

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = subtissC, do.return = TRUE, group.by = "plate.barcode")

Final coloring

Color by cell ontology class on the original TSNE.

TSNEPlot(object = subtissC, do.label = TRUE, do.return = TRUE, group.by = "free_annotation")

TSNEPlot(object = subtissC, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

Subset D == hematopoietic precursor cells (Cluster 0)

This subset contains hematopoietic multipotent progenitor (MPP) cells and a very minute fraction of Hematopoietic stem cells (HSC).

subtissD = SubsetData(tiss, ident.use = c(0))
subtissD <- subtissD %>% ScaleData() %>% 
  FindVariableGenes(do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
  RunPCA(do.print = FALSE)
[1] "Scaling data matrix"

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |============================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

PCHeatmap(object = subtissD, pc.use = 1:3, cells.use = 500, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)

PCElbowPlot(subtissD)

sub.n.pcs = 20
sub.res.use = 1
subtissD <- subtissD %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.use, print.output = 0, save.SNN = TRUE) %>%
    RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=65)
TSNEPlot(object = subtissD, do.label = T, pt.size = 1.2, label.size = 4)

previous_annotation_table(subtissD)
[1] "previous_free_annotation"
                                             
                                                0   1   2   3   4   5   6
  common lymphoid progenitor                    0   0   1 123   3   0   0
  granulocyte monocyte progenitor cell          0   0   0   0   2  60   0
  hematopoietic stem cell enriched fraction    41   1   2   0   0   0   1
  HSC enriched fraction                         1  92   0   0   0   0   0
  megakaryocyte-erythroid progenitor cell       0   0   0   0   0   0  46
  NA                                           38   1  21  23  15   4   4
  Slamf1-negative multipotent progenitor cell 188  81 129   9  37   0   2
  Slamf1-positive multipotent progenitor cell   0   0   9   1  78   0   1
[1] "previous_cell_ontology_class"
                                      
                                        0  1  2  3  4  5  6
  granulocyte monocyte progenitor cell  0  0  0  0  2 60  0
  monocyte                              0  0  1  0  0  0  0
  NA                                   38  1 21 23 15  4  4

Check expression of genes of interset.

{r} # subtissD.markers <- FindAllMarkers(object = subtissD, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25) #

{r} # subtissD.markers %>% group_by(cluster) %>% top_n(6, avg_logFC) #

The multitude of clusters of each type correspond mostly to individual animals/sexes.

table(FetchData(subtissD, c('mouse.id','ident')) %>% droplevels())
        ident
mouse.id   0   1   2   3   4   5   6
  3_10_M  19 166   5  25  60  45  27
  3_38_F   0   0   0   0   0   1   2
  3_39_F   4   2   2   7   4  13   6
  3_8_M  138   2  83  66  36   4   7
  3_9_M  107   5  73  58  35   1  12
sub.cluster.ids <- c(0, 1, 2, 3, 4, 5, 6)
sub.free_annotation <- c(NA, NA, NA, NA, NA, NA, NA)
sub.cell_ontology_class <- c(
  "Slamf1-negative multipotent progenitor cell",
  "hematopoietic precursor cell",
  "Slamf1-negative multipotent progenitor cell",
  "common lymphoid progenitor",
  "Slamf1-positive multipotent progenitor cell",
  "granulocyte monocyte progenitor cell",
  "megakaryocyte-erythroid progenitor cell"
  )
subtissD = stash_annotations(subtissD, sub.cluster.ids, sub.free_annotation, sub.cell_ontology_class)
tiss = stash_subtiss_in_tiss(tiss, subtissD)
head(tiss@meta.data)
data.frame(sub.cluster.ids, sub.cell_ontology_class, sub.free_annotation)
head(subtissD@meta.data)

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = subtissD, do.return = TRUE, group.by = "plate.barcode")

Final coloring

Color by cell ontology class on the original TSNE.

# TSNEPlot(object = subtissD, do.label = TRUE, do.return = TRUE, group.by = "free_annotation")
TSNEPlot(object = subtissD, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

Final coloring

Color by cell ontology class on the original TSNE.

TSNEPlot(object = tiss, do.label = TRUE, do.return = TRUE, group.by = "free_annotation")

TSNEPlot(object = tiss, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

Subcluster the clusters 7 of tiss

Subset E == granulocyte monocyte progenitor cell, monocyte

subtissE = SubsetData(tiss, ident.use = c(7))
subtissE <- subtissE %>% ScaleData() %>% 
  FindVariableGenes(do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
  RunPCA(do.print = FALSE)
[1] "Scaling data matrix"

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |============================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

PCHeatmap(object = subtissE, pc.use = 1:3, cells.use = 170, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)

PCElbowPlot(subtissE)

sub.n.pcs = 20
sub.res.use = 1
subtissE <- subtissE %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.use, print.output = 0, save.SNN = TRUE, force=TRUE) %>%
    RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=60)
TSNEPlot(object = subtissE, do.label = T, pt.size = 1.2, label.size = 4)

previous_annotation_table(subtissE)
[1] "previous_free_annotation"
    
     0 1 2 3
  NA 3 5 1 2
[1] "previous_cell_ontology_class"
                                      
                                        0  1  2  3
  granulocyte monocyte progenitor cell  0  0  3 66
  monocyte                             99 87 68  2
  NA                                    3  5  1  2

Check expression of genes of interset.

{r} # subtissE.markers <- FindAllMarkers(object = subtissE, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25) #

{r} # subtissE.markers %>% group_by(cluster) %>% top_n(6, avg_logFC) #

The multitude of clusters of each type correspond mostly to individual animals/sexes.

table(FetchData(subtissE, c('mouse.id','ident')) %>% droplevels())
        ident
mouse.id  0  1  2  3
  3_10_M 22  2 30  4
  3_38_F  2 58  6 32
  3_39_F 37  7  4 22
  3_8_M  28  6 20  6
  3_9_M  13 19 12  6
sub.cluster.ids <- c(0, 1, 2, 3)
sub.free_annotation <- c(
  NA, NA, NA, NA
  )
sub.cell_ontology_class <-
  c(
  "monocyte",
  "monocyte",
  "monocyte",
  "granulocyte monocyte progenitor cell"
  )
subtissE = stash_annotations(subtissE, sub.cluster.ids, sub.free_annotation, sub.cell_ontology_class)
tiss = stash_subtiss_in_tiss(tiss, subtissE)
head(tiss@meta.data)

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = subtissE, do.return = TRUE, group.by = "plate.barcode")

Final coloring

Color by cell ontology class on the original TSNE.

# TSNEPlot(object = subtissE, do.label = TRUE, do.return = TRUE, group.by = "free_annotation")
TSNEPlot(object = subtissE, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

Final coloring - entire tissue!

Color by cell ontology class on the original TSNE.

TSNEPlot(object = tiss, do.label = TRUE, do.return = TRUE, group.by = "free_annotation")

TSNEPlot(object = tiss, do.label = TRUE, do.return = TRUE, group.by = "cell_ontology_class")

Save the Robject for later

filename = here('00_data_ingest', '04_tissue_robj_generated', 
                     paste0("facs_", tissue_of_interest, "_seurat_tiss.Robj"))
print(filename)
[1] "/Users/olgabot/code/tabula-muris/00_data_ingest/04_tissue_robj_generated/facs_Marrow_seurat_tiss.Robj"
save(tiss, file=filename)
# To reload a saved object
# filename = here('00_data_ingest', '04_tissue_robj_generated', 
#                      paste0("facs", tissue_of_interest, "_seurat_tiss.Robj"))
# load(file=filename)

Export the final metadata

Write the cell ontology and free annotations to CSV.

save_annotation_csv(tiss, tissue_of_interest, "facs")
LS0tCnRpdGxlOiAiTWFycm93IEZBQ1MgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KClNwZWNpZnkgdGhlIHRpc3N1ZSBvZiBpbnRlcmVzdCwgcnVuIHRoZSBib2lsZXJwbGF0ZSBjb2RlIHdoaWNoIHNldHMgdXAgdGhlIGZ1bmN0aW9ucyBhbmQgZW52aXJvbm1lbnQsIGxvYWQgdGhlIHRpc3N1ZSBvYmplY3QuCgpgYGB7cn0KdGlzc3VlX29mX2ludGVyZXN0ID0gIk1hcnJvdyIKbGlicmFyeShoZXJlKQpzb3VyY2UoaGVyZSgiMDBfZGF0YV9pbmdlc3QiLCAiMDJfdGlzc3VlX2FuYWx5c2lzX3JtZCIsICJib2lsZXJwbGF0ZS5SIikpCnRpc3MgPSBsb2FkX3Rpc3N1ZV9mYWNzKHRpc3N1ZV9vZl9pbnRlcmVzdCkKYGBgCgpWaXN1YWxpemUgdG9wIGdlbmVzIGluIHByaW5jaXBhbCBjb21wb25lbnRzCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQpQQ0hlYXRtYXAob2JqZWN0ID0gdGlzcywgcGMudXNlID0gMTozLCBjZWxscy51c2UgPSA1MDAsIGRvLmJhbGFuY2VkID0gVFJVRSwgbGFiZWwuY29sdW1ucyA9IEZBTFNFLCBudW0uZ2VuZXMgPSA4KQpgYGAKCkxhdGVyIG9uIChpbiBGaW5kQ2x1c3RlcnMgYW5kIFRTTkUpIHlvdSB3aWxsIHBpY2sgYSBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMgdG8gdXNlLiBUaGlzIGhhcyB0aGUgZWZmZWN0IG9mIGtlZXBpbmcgdGhlIG1ham9yIGRpcmVjdGlvbnMgb2YgdmFyaWF0aW9uIGluIHRoZSBkYXRhIGFuZCwgaWRlYWxseSwgc3VwcmVzc2luZyBub2lzZS4gVGhlcmUgaXMgbm8gY29ycmVjdCBhbnN3ZXIgdG8gdGhlIG51bWJlciB0byB1c2UsIGJ1dCBhIGRlY2VudCBydWxlIG9mIHRodW1iIGlzIHRvIGdvIHVudGlsIHRoZSBwbG90IHBsYXRlYXVzLgoKYGBge3J9ClBDRWxib3dQbG90KG9iamVjdCA9IHRpc3MpCmBgYAoKQ2hvb3NlIHRoZSBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMgdG8gdXNlLgpgYGB7cn0KIyBTZXQgbnVtYmVyIG9mIHByaW5jaXBhbCBjb21wb25lbnRzLiAKbi5wY3MgPSAxOApgYGAKCgpUaGUgY2x1c3RlcmluZyBpcyBwZXJmb3JtZWQgYmFzZWQgb24gYSBuZWFyZXN0IG5laWdoYm9ycyBncmFwaC4gQ2VsbHMgdGhhdCBoYXZlIHNpbWlsYXIgZXhwcmVzc2lvbiB3aWxsIGJlIGpvaW5lZCB0b2dldGhlci4gVGhlIExvdXZhaW4gYWxnb3JpdGhtIGxvb2tzIGZvciBncm91cHMgb2YgY2VsbHMgd2l0aCBoaWdoIG1vZHVsYXJpdHktLW1vcmUgY29ubmVjdGlvbnMgd2l0aGluIHRoZSBncm91cCB0aGFuIGJldHdlZW4gZ3JvdXBzLiBUaGUgcmVzb2x1dGlvbiBwYXJhbWV0ZXIgZGV0ZXJtaW5lcyB0aGUgc2NhbGUuLi5oaWdoZXIgcmVzb2x1dGlvbiB3aWxsIGdpdmUgbW9yZSBjbHVzdGVycywgbG93ZXIgcmVzb2x1dGlvbiB3aWxsIGdpdmUgZmV3ZXIuCgpGb3IgdGhlIHRvcC1sZXZlbCBjbHVzdGVyaW5nLCBhaW0gdG8gdW5kZXItY2x1c3RlciBpbnN0ZWFkIG9mIG92ZXItY2x1c3Rlci4gSXQgd2lsbCBiZSBlYXN5IHRvIHN1YnNldCBncm91cHMgYW5kIGZ1cnRoZXIgYW5hbHl6ZSB0aGVtIGJlbG93LgoKYGBge3J9CiMgU2V0IHJlc29sdXRpb24gCnJlcy51c2VkIDwtIDAuNQoKdGlzcyA8LSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gdGlzcywgcmVkdWN0aW9uLnR5cGUgPSAicGNhIiwgZGltcy51c2UgPSAxOm4ucGNzLCAKICAgIHJlc29sdXRpb24gPSByZXMudXNlZCwgcHJpbnQub3V0cHV0ID0gMCwgc2F2ZS5TTk4gPSBUUlVFKQpgYGAKClRvIHZpc3VhbGl6ZSAKYGBge3J9CiMgSWYgY2VsbHMgYXJlIHRvbyBzcHJlYWQgb3V0LCB5b3UgY2FuIHJhaXNlIHRoZSBwZXJwbGV4aXR5LiBJZiB5b3UgaGF2ZSBmZXcgY2VsbHMsIHRyeSBhIGxvd2VyIHBlcnBsZXhpdHkgKGJ1dCBuZXZlciBsZXNzIHRoYW4gMTApLgp0aXNzIDwtIFJ1blRTTkUob2JqZWN0ID0gdGlzcywgZGltcy51c2UgPSAxOm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTg0KQpgYGAKCmBgYHtyfQojIG5vdGUgdGhhdCB5b3UgY2FuIHNldCBkby5sYWJlbD1UIHRvIGhlbHAgbGFiZWwgaW5kaXZpZHVhbCBjbHVzdGVycwpUU05FUGxvdChvYmplY3QgPSB0aXNzLCBkby5sYWJlbCA9IFQpCmBgYAojIyBDb21wYXJlIHRvIHByZXZpb3VzIGFubm90YXRpb25zCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQptZXRob2QgPSAiZmFjcyIKdGlzcyA9IGNvbXBhcmVfcHJldmlvdXNfYW5ub3RhdGlvbih0aXNzLCB0aXNzdWVfb2ZfaW50ZXJlc3QsIG1ldGhvZCwgZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICcwM190aXNzdWVfYW5ub3RhdGlvbl9jc3YnLCAKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAodGlzc3VlX29mX2ludGVyZXN0LCAiXyIsIG1ldGhvZCwgIl9hbm5vdGF0aW9uX3JhaHVsLmNzdiIpKSkKVFNORVBsb3Qob2JqZWN0ID0gdGlzcywgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAicHJldmlvdXNfY2VsbF9vbnRvbG9neV9jbGFzcyIpClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gInByZXZpb3VzX2ZyZWVfYW5ub3RhdGlvbiIpCmBgYAoKCgoKQ2hlY2sgZXhwcmVzc2lvbiBvZiBnZW5lcyBvZiBpbnRlcnNldC4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTE3NCwgZmlnLndpZHRoPTE1fQpnZW5lc190b19jaGVjayA9IGMoJ0l0Z2FtJywgJ0lsN3InLCAnS2l0JywgJ0F0eG4xJywgJ0ZjZ3IzJywgJ0ZsdDMnLCAnQ2QzNCcsICdTbGFtZjEnLCAnR3ByNTYnLCAnU3RtbjEnLCAnTWtpNjcnLCAnVG1lbTE3NmInLCAgJ0l0Z2FsJywgJ0l0Z2F4JywgJ0VtcjEnLCAnQ2Q2OCcsICdDZDY5JywgJ0ZjZ3I0JywgJ01wZWcxJywgJ0l0Z2IyJywgJ0FobmFrJywgJ1BsZDQnLCAnQ2QzZScsICdDZDQnLCAnQ2Q4YScsICdMeTZkJywgJ0NkMjcnLCAnQ3IyJywgJ0ZjZXIyYScsICdDZDInLCAnQ2Q3JywgJ01tZScsICdUaHkxJywgJ0tscmIxYScsICdTMTAwYTExJywgJ0x0ZicsICdOZ3AnLCAnRmNlcjFnJywgJ1BnbHlycDEnLCAnTGNuMicsICdDYW1wJywgJ0hwJywgJ0x5Nmc2YycsICdMeTZnNmUnLCAnUHRwcmMnLCAnQ2QxOScsICdNczRhMScsICdDb3g2YTInLCAnSXJmOCcsICdDZDc0JywgJ0NoY2hkMTAnLCAnQ25wJywgJ0NkNzlhJywgJ0NkNzliJywgJ1ZwcmViMScsICdWcHJlYjMnLCAnQ2QzOCcsICdDZDIyJywgJ0NkMjRhJywgJ0NkNDAnLCAnQ2Q0OCcsICdDZDUzJywgJ0NkODEnLCAnQ2Q4NCcsICdDeGNyNCcsICdDeGNyNScsICdDY3I2JywgJ0NkMjAwJywgJ0x5OScsICdBYmNiMWInLCAnVGxyOScsICdTbGFtZjYnLCAnSDItRWEtcHMnLCAnUGF4NScsICdGb3hvMScsICdLbGY0JywgJ0tsZjknLCAnTWl0ZicsICdQb3UyYWYxJywgJ1pidGIxNicsICdTcGliJywgJ1NwbicsICdEbnR0JywgJ1JhZzEnLCAnUmFnMicsICdJbDJyYScsICdQZHprMWlwMScsICdMeTZhJywgJ0l0Z2EyYicsICdGb3MnLCAnSnVuYicsICdNeWwxMCcsICdKdW4nLCAnTW4xJywgJ1MxMDBhOScsICdDY2w5JywgJ1RjZjMnLCAnRWJmMScsICdJa3pmMScsICdTZnBpMScsICdDZDFkMScsICdFZ3IyJywgJ0NkMTQnLCAnTXBsJywgJ0lsM3JhJywgJ0JwZ20nLCAnQmV0YS1zJywgJ0hiYi1iMicsICdDcGEzJywgJ0ZjZXIxYScsICdNY3B0OCcsICdDY2wzJywgJ0dhdGExJywgJ0dhdGEyJywgJ0NlYnBhJykKI2dlbmVzX3RvX2NoZWNrID0gYygnQWxiJywgJ0N5cDJmMicsICdDeXAyZTEnLCAnSGFtcCcpCgojIEZlYXR1cmVQbG90KHRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSwgbkNvbCA9IDMpCmBgYAoKRG90cGxvdHMgbGV0IHlvdSBzZWUgdGhlIGludGVuc2l0eSBvZiBleHBwcmVzc2lvbiBhbmQgdGhlIGZyYWN0aW9uIG9mIGNlbGxzIGV4cHJlc3NpbmcgZm9yIGVhY2ggb2YgeW91ciBnZW5lcyBvZiBpbnRlcmVzdC4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04NH0KIyBUbyBjaGFuZ2UgdGhlIHktYXhpcyB0byBzaG93IHJhdyBjb3VudHMsIGFkZCB1c2UucmF3ID0gVC4KRG90UGxvdCh0aXNzLCBnZW5lc190b19jaGVjaywgcGxvdC5sZWdlbmQgPSBUKQpgYGAKCkhvdyBiaWcgYXJlIHRoZSBjbHVzdGVycz8KYGBge3J9CnRhYmxlKHRpc3NAaWRlbnQpCmBgYAoKPCEtLSBXaGljaCBtYXJrZXJzIGlkZW50aWZ5IGEgc3BlY2lmaWMgY2x1c3Rlcj8gLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBjbHVzdC5tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHRpc3MsIGlkZW50LjEgPSAwLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCB0aHJlc2gudXNlID0gMC4yNSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gcHJpbnQoeCA9IGhlYWQoeD0gY2x1c3QubWFya2VycywgbiA9IDEwKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBZb3UgY2FuIGFsc28gY29tcHV0ZSBhbGwgbWFya2VycyBmb3IgYWxsIGNsdXN0ZXJzIGF0IG9uY2UuIFRoaXMgbWF5IHRha2Ugc29tZSB0aW1lLiAtLT4KPCEtLSBgYGB7cn0gLS0+CjwhLS0gdGlzcy5tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IHRpc3MsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIHRocmVzaC51c2UgPSAwLjI1KSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIGhlYWQodGlzcy5tYXJrZXJzKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIERpc3BsYXkgdGhlIHRvcCBtYXJrZXJzIHlvdSBjb21wdXRlZCBhYm92ZS4gLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIHRpc3MubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDUsIGF2Z19sb2dGQykgLS0+CjwhLS0gYGBgIC0tPgoKIyMgQXNzaWduaW5nIGNlbGwgdHlwZSBpZGVudGl0eSB0byBjbHVzdGVycwoKQXQgYSBjb2Fyc2UgbGV2ZWwsIHdlIGNhbiB1c2UgY2Fub25pY2FsIG1hcmtlcnMgdG8gbWF0Y2ggdGhlIHVuYmlhc2VkIGNsdXN0ZXJpbmcgdG8ga25vd24gY2VsbCB0eXBlczoKYGBge3J9CnByZXZpb3VzX2Fubm90YXRpb25fdGFibGUodGlzcykKYGBgCgoKYGBge3J9CiMgc3Rhc2ggY3VycmVudCBjbHVzdGVyIElEcwp0aXNzIDwtIFN0YXNoSWRlbnQob2JqZWN0ID0gdGlzcywgc2F2ZS5uYW1lID0gImNsdXN0ZXIuaWRzIikKCiMgZW51bWVyYXRlIGN1cnJlbnQgY2x1c3RlciBJRHMgYW5kIHRoZSBsYWJlbHMgZm9yIHRoZW0KY2x1c3Rlci5pZHMgPC0gYygwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyKQpmcmVlX2Fubm90YXRpb24gPC0gYyhOQSwgTkEsICJwcmUtQiBjZWxsIChQaGlsYWRlbHBoaWEgbm9tZW5jbGF0dXJlKSIsCiAgICAgICAgICAgICAgICAgICAgIE5BLCBOQSwgTkEsIE5BLCBOQSwgTkEsIE5BLCBOQSwgTkEsIE5BKQpjZWxsX29udG9sb2d5X2NsYXNzIDwtYygKICBOQSwgIyBDbHVzdGVyIDAgaXMgYSBtaXggb2YgcHJvZ2VuaXRvcnMgYW5kIHByZWN1cnNvcnMKICAibmFpdmUgQiBjZWxsIiwgCiAgInByZWN1cnNvciBCIGNlbGwiLCAKICAiZ3JhbnVsb2N5dGUiLCAKICAiaGVtYXRvcG9pZXRpYyBwcmVjdXJzb3IgY2VsbCIsIAogICJncmFudWxvY3l0ZSIsCiAgImltbWF0dXJlIEIgY2VsbCIsIAogIE5BLCAjIENsdXN0ZXIgNyBpcyBhIG1peCBvZiBtb25vY3l0ZXMgYW5kIGdyYW51bG9jeXRlIHByb2dlbml0b3JzCiAgImxhdGUgcHJvLUIgY2VsbCIsIAogICJncmFudWxvY3l0b3BvaWV0aWMgY2VsbCIsCiAgIm1hY3JvcGhhZ2UiLAogIE5BLCAjIENsdXN0ZXIgMTEgaXMgYSBtaXggb2YgVCwgTktUIGFuZCBCIGNlbGxzCiAgTkEgIyBDbHVzdGVyIDEyIGlzIGEgbWl4IG9mIGJhc29waGlsLCBCIGNlbGxzLCBpbW1hdHVyZSBOSyBjZWxscywgbWF0dXJlIE5LIGNlbGxzLCBwcmUtbmF0dXJhbCBraWxsZXIgY2VsbHMKKQoKdGlzcyA9IHN0YXNoX2Fubm90YXRpb25zKHRpc3MsIGNsdXN0ZXIuaWRzLCBmcmVlX2Fubm90YXRpb24sIGNlbGxfb250b2xvZ3lfY2xhc3MpCgpkYXRhLmZyYW1lKGNsdXN0ZXIuaWRzLCBjZWxsX29udG9sb2d5X2NsYXNzLCBmcmVlX2Fubm90YXRpb24pClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLmxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuNSwgZ3JvdXAuYnk9J2NlbGxfb250b2xvZ3lfY2xhc3MnKQpgYGAKCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKCkNvbG9yIGJ5IG1ldGFkYXRhLCBsaWtlIHBsYXRlIGJhcmNvZGUsIHRvIGNoZWNrIGZvciBiYXRjaCBlZmZlY3RzLgpgYGB7cn0KVFNORVBsb3Qob2JqZWN0ID0gdGlzcywgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAicGxhdGUuYmFyY29kZSIpCmBgYAoKUHJpbnQgYSB0YWJsZSBzaG93aW5nIHRoZSBjb3VudCBvZiBjZWxscyBpbiBlYWNoIGlkZW50aXR5IGNhdGVnb3J5IGZyb20gZWFjaCBwbGF0ZS4KCmBgYHtyfQp0YWJsZShhcy5jaGFyYWN0ZXIodGlzc0BpZGVudCksIGFzLmNoYXJhY3Rlcih0aXNzQG1ldGEuZGF0YSRwbGF0ZS5iYXJjb2RlKSkKYGBgCgojIyBSZWRvIFN1YmNsdXN0ZXIgYXMgcGVyIHRoZSBjb2RlIGZyb20gcGFuY3JlYXMgcGxhdGUgUm1kLCB3aGljaCBpcyB3aXRob3V0IHJlZ3Jlc3Npbmcgb3V0IHJpYm9zb21hbCBnZW5lcwojIyAKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgoKIyBTdWJzZXQgQSA9PSBUX05LX05LVCBjZWxsIChDbHVzdGVycyAxMSwgMTIpCgpgYGB7cn0Kc3VidGlzc0EgPSBTdWJzZXREYXRhKHRpc3MsIGlkZW50LnVzZSA9IGMoMTEsIDEyKSkKYGBgCgpgYGB7cn0Kc3VidGlzc0EgPC0gc3VidGlzc0EgJT4lIFNjYWxlRGF0YSgpICU+JSAKICBGaW5kVmFyaWFibGVHZW5lcyhkby5wbG90ID0gVFJVRSwgeC5oaWdoLmN1dG9mZiA9IEluZiwgeS5jdXRvZmYgPSAwLjUpICU+JQogIFJ1blBDQShkby5wcmludCA9IEZBTFNFKQpgYGAKCmBgYHtyfQpQQ0hlYXRtYXAob2JqZWN0ID0gc3VidGlzc0EsIHBjLnVzZSA9IDE6MywgY2VsbHMudXNlID0gMTAwLCBkby5iYWxhbmNlZCA9IFRSVUUsIGxhYmVsLmNvbHVtbnMgPSBGQUxTRSwgbnVtLmdlbmVzID0gOCkKUENFbGJvd1Bsb3Qoc3VidGlzc0EpCmBgYAoKCmBgYHtyfQpzdWIubi5wY3MgPSA0CnN1Yi5yZXMudXNlID0gMQpzdWJ0aXNzQSA8LSBzdWJ0aXNzQSAlPiUgRmluZENsdXN0ZXJzKHJlZHVjdGlvbi50eXBlID0gInBjYSIsIGRpbXMudXNlID0gMTpzdWIubi5wY3MsIAogICAgcmVzb2x1dGlvbiA9IHN1Yi5yZXMudXNlLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUpICU+JQogICAgUnVuVFNORShkaW1zLnVzZSA9IDE6c3ViLm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTQ0KQoKVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0EsIGRvLmxhYmVsID0gVCwgcHQuc2l6ZSA9IDEuMiwgbGFiZWwuc2l6ZSA9IDQpCgpgYGAKQ2hlY2sgZXhwcmVzc2lvbiBvZiBnZW5lcyBvZiBpbnRlcnNldC4KCiMgYGBge3J9CiMgc3VidGlzc0EubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzQSwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCiMgYGBgCiMgCiMgYGBge3J9CiMgc3VidGlzc0EubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDYsIGF2Z19sb2dGQykKIyBgYGAKIyAKCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzQSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAicHJldmlvdXNfY2VsbF9vbnRvbG9neV9jbGFzcyIpClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3NBLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwcmV2aW91c19mcmVlX2Fubm90YXRpb24iKQpgYGAKCgoKYGBge3J9CnByZXZpb3VzX2Fubm90YXRpb25fdGFibGUoc3VidGlzc0EpCmBgYAoKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTEwMiwgZmlnLndpZHRoPTE1fQpnZW5lc190b19jaGVjayA9IGMoJ0NkNicsJ0lsN3InLCdDdGxhNCcsJ0NkOGIxJywgJ0NkNjknLCAnQ3hjcjYnLCAnQ2Q0JywgJ0NkOGEnLCAnQ2Q4YjEnLCAnQ2NyNycsICdUY2Y3JywgJ0xlZjEnLCAnTW1wOScsICdUbmZyc2Y0JywgJ0ZveHAzJywgJ0xjbjInLCAnS2xyYzEnLCAnQ2QxNjAnLCAnQ3RsYTJhJywgJ1R5cm9icCcsICdOY3IxJywgJ0NkM2UnLCAnS2xyYjFhJywgJ0tscmIxYycsICdQcmYxJywgJ1NlcnBpbmI5JywgJ0x5ejInLCAnTmdwJywgJ0hwJywgJ0x5NmMyJywgJ0NkNzlhJywgJ0NkNzQnLCAnSDItQWEnLCAnSDItQWIxJywgJ0NkNzliJywgJ0gyLUViMScsICdDY25hMicsICdUb3AyYScsICdScm0yJywgJ05rZzcnLCAnQ2QxZDEnLCAnRWdyMicsICdDZDE5JywgJ01zNGExJywgJ0NoY2hkMTAnLCAnQ25wJywgJ1JhZzEnLCAnUmFnMicsICdEbnR0JywgJ1BheDUnLCAnSWwycmEnLCAnQ3hjcjUnLCAnQ2NyNicsICdDcjInLCAnQ2QyMicsICdWcHJlYjMnLCAnTWtpNjcnLCAnU3RtbjEnLCAnSWwycmInLCAnUGxkNCcsICdDZDY4JywgJ01wZWcxJywgJ0VtcjEnLCAnQWRhbXRzMTQnLCAnSXRnYXgnLCAnU3R5azEnLCAnVWd0MWE3YycsICdLaGRjMWEnLCAnQ2FyNWInLCAnR3ptYScsICdDbWExJywgJ0E0MzAwODRQMDVSaWsnLCAnQ2NsNCcsICdTaDJkMWIxJywgJ05jYW0xJywgJ0tscmExJywgJ0NkMzQnLCAnSWwycmInLCAnSXRnYTQnLCAnSXRnYjcnKQoKIyAjIEZlYXR1cmVQbG90KHN1YnRpc3NBLCBnZW5lc190b19jaGVjaywgcHQuc2l6ZSA9IDEsIG5Db2wgPSAzKQpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CiNEb3RQbG90KHN1YnRpc3NBLCBnZW5lc190b19jaGVjaywgY29sLm1heCA9IDIuNSwgcGxvdC5sZWdlbmQgPSBULCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQpgYGAKCgpUaGUgbXVsdGl0dWRlIG9mIGNsdXN0ZXJzIG9mIGVhY2ggdHlwZSBjb3JyZXNwb25kIG1vc3RseSB0byBpbmRpdmlkdWFsIGFuaW1hbHMvc2V4ZXMuCgpgYGB7cn0KdGFibGUoRmV0Y2hEYXRhKHN1YnRpc3NBLCBjKCdtb3VzZS5pZCcsJ2lkZW50JykpICU+JSBkcm9wbGV2ZWxzKCkpCmBgYAoKYGBge3J9CnN1Yi5jbHVzdGVyLmlkcyA8LSBjKDAsIDEsIDIsIDMsIDQsIDUsIDYpCnN1Yi5mcmVlX2Fubm90YXRpb24gPC0gYygicmVndWxhdG9yeSBhbmQgaW1tYXR1cmUgVCBjZWxsIiwgTkEsICJDZDNlKyBLbHJiMSsgQiBjZWxsIiwgIE5BLCBOQSwgTkEsIE5BKQoiIgpzdWIuY2VsbF9vbnRvbG9neV9jbGFzcyA8LWMoIlQgY2VsbCIsICJtYXR1cmUgbmF0dXJhbCBraWxsZXIgY2VsbCIsIkIgY2VsbCIsICAiaW1tYXR1cmUgTksgVCBjZWxsIiwgImltbWF0dXJlIG5hdHVyYWwga2lsbGVyIGNlbGwiLCAiYmFzb3BoaWwiLCAgInByZS1uYXR1cmFsIGtpbGxlciBjZWxsIikKCnN1YnRpc3NBID0gc3Rhc2hfYW5ub3RhdGlvbnMoc3VidGlzc0EsIHN1Yi5jbHVzdGVyLmlkcywgc3ViLmZyZWVfYW5ub3RhdGlvbiwgc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MpCnRpc3MgPSBzdGFzaF9zdWJ0aXNzX2luX3Rpc3ModGlzcywgc3VidGlzc0EpCmhlYWQodGlzc0BtZXRhLmRhdGEpCgpkYXRhLmZyYW1lKHN1Yi5jbHVzdGVyLmlkcywgc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MsIHN1Yi5mcmVlX2Fubm90YXRpb24pCmBgYAoKIyMgQ2hlY2tpbmcgZm9yIGJhdGNoIGVmZmVjdHMKCkNvbG9yIGJ5IG1ldGFkYXRhLCBsaWtlIHBsYXRlIGJhcmNvZGUsIHRvIGNoZWNrIGZvciBiYXRjaCBlZmZlY3RzLgpgYGB7cn0KVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0EsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gInBsYXRlLmJhcmNvZGUiKQpgYGAKCiMgRmluYWwgY29sb3JpbmcKCkNvbG9yIGJ5IGNlbGwgb250b2xvZ3kgY2xhc3Mgb24gdGhlIG9yaWdpbmFsIFRTTkUuCgpgYGB7cn0KVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0EsIGRvLmxhYmVsID0gVFJVRSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiY2VsbF9vbnRvbG9neV9jbGFzcyIpClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3NBLCBkby5sYWJlbCA9IFRSVUUsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gImZyZWVfYW5ub3RhdGlvbiIpCmBgYAoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFN1YnNldCBCID09IHJlZ3VsYXRvcnlfaW1tYXR1cmUgVCBjZWxsIChDbHVzdGVyIDApCiMjIE11bHRpcGxlIGNlbGwtdHlwZXMgaW4gdGhlIGNsdXN0ZXIgMCBvZiBzdWJ0aXNzIChvcmlnaW5hbCBjbHVzdGVyIDcpCiMjIHN1YmNsdXN0ZXIgdGhlIGNsdXN0ZXIgMCAocmVndWxhdG9yeV9pbW1hdHVyZSBUIGNlbGwpIG9mIHN1YnRpc3MgKG9yaWdpbmFsIGNsdXN0ZXIgNykKCmBgYHtyfQpzdWJ0aXNzQiA9IFN1YnNldERhdGEoc3VidGlzc0EsIGlkZW50LnVzZSA9IGMoMCkpCmBgYAoKYGBge3J9CnN1YnRpc3NCIDwtIHN1YnRpc3NCICU+JSBTY2FsZURhdGEoKSAlPiUgCiAgRmluZFZhcmlhYmxlR2VuZXMoZG8ucGxvdCA9IFRSVUUsIHguaGlnaC5jdXRvZmYgPSBJbmYsIHkuY3V0b2ZmID0gMC41KSAlPiUKICBSdW5QQ0EoZG8ucHJpbnQgPSBGQUxTRSkKYGBgCgpgYGB7cn0KUENIZWF0bWFwKG9iamVjdCA9IHN1YnRpc3NCLCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDE1MCwgZG8uYmFsYW5jZWQgPSBUUlVFLCBsYWJlbC5jb2x1bW5zID0gRkFMU0UsIG51bS5nZW5lcyA9IDgpClBDRWxib3dQbG90KHN1YnRpc3NCKQpgYGAKCgpgYGB7cn0Kc3ViLm4ucGNzID0gMwpzdWIucmVzLnVzZSA9IDEKc3VidGlzc0IgPC0gc3VidGlzc0IgJT4lIEZpbmRDbHVzdGVycyhyZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCBkaW1zLnVzZSA9IDE6c3ViLm4ucGNzLCAKICAgIHJlc29sdXRpb24gPSBzdWIucmVzLnVzZSwgcHJpbnQub3V0cHV0ID0gMCwgc2F2ZS5TTk4gPSBUUlVFKSAlPiUKICAgIFJ1blRTTkUoZGltcy51c2UgPSAxOnN1Yi5uLnBjcywgc2VlZC51c2UgPSAxMCwgcGVycGxleGl0eT0xMikKClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3NCLCBkby5sYWJlbCA9IFQsIHB0LnNpemUgPSAxLjIsIGxhYmVsLnNpemUgPSA0KQoKYGBgCmBgYHtyfQpwcmV2aW91c19hbm5vdGF0aW9uX3RhYmxlKHN1YnRpc3NCKQpgYGAKCkNoZWNrIGV4cHJlc3Npb24gb2YgZ2VuZXMgb2YgaW50ZXJzZXQuCgojIGBgYHtyfQojIHN1YnRpc3NCLm1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gc3VidGlzc0IsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIHRocmVzaC51c2UgPSAwLjI1KQojIGBgYAojIAojIGBgYHtyfQojIHN1YnRpc3NCLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3Bfbig2LCBhdmdfbG9nRkMpCiMgYGBgCiMgCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9ODQsIGZpZy53aWR0aD0xNX0KZ2VuZXNfdG9fY2hlY2sgPSBjKCdDZDYnLCdJbDdyJywnQ3RsYTQnLCdDZDhiMScsICdDZDY5JywgJ0N4Y3I2JywgJ0NkNCcsICdDZDhhJywgJ0NkOGIxJywgJ0NjcjcnLCAnVGNmNycsICdMZWYxJywgJ01tcDknLCAnVG5mcnNmNCcsICdGb3hwMycsICdMY24yJywgJ0tscmMxJywgJ0NkMTYwJywgJ0N0bGEyYScsICdUeXJvYnAnLCAnQ2QzZScsICdLbHJiMWEnLCAnS2xyYjFjJywgJ1ByZjEnLCAnU2VycGluYjknLCAnTHl6MicsICdOZ3AnLCAnSHAnLCAnTHk2YzInLCAnQ2Q3OWEnLCAnQ2Q3NCcsICdIMi1BYScsICdIMi1BYjEnLCAnQ2Q3OWInLCAnSDItRWIxJywgJ0NjbmEyJywgJ1RvcDJhJywgJ1JybTInLCAnTmtnNycsICdDZDFkMScsICdFZ3IyJywgJ0NkMTknLCAnTXM0YTEnLCAnQ2hjaGQxMCcsICdDbnAnLCAnUmFnMicsICdEbnR0JywgJ0lsMnJhJywgJ0N4Y3I1JywgJ0NjcjYnLCAnQ3IyJywgJ0NkMjInLCAnVnByZWIzJywgJ01raTY3JywgJ1N0bW4xJywgJ0lsMnJiJywgJ1BsZDQnLCAnQ2Q2OCcsICdNcGVnMScsICdVZ3QxYTdjJywgJ0NhcjViJywgJ0d6bWEnLCAnQTQzMDA4NFAwNVJpaycsICdDY2w0JywgJ05jYW0xJywgJ0tscmExJywgJ0NkMzQnLCAnSXRnYTQnLCAnSXRnYjcnLCAnVGdmYjEnLCAnSWwxMCcpCgojIEZlYXR1cmVQbG90KHN1YnRpc3NCLCBnZW5lc190b19jaGVjaywgcHQuc2l6ZSA9IDEsIG5Db2wgPSAzKQpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CiNEb3RQbG90KHN1YnRpc3NCLCBnZW5lc190b19jaGVjaywgY29sLm1heCA9IDIuNSwgcGxvdC5sZWdlbmQgPSBULCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQpgYGAKCkZyb20gdGhlc2UgZ2VuZXMsIGl0IGFwcGVhcnMgdGhhdCB0aGUgY2x1c3RlcnMgcmVwcmVzZW50OgoKVGhlIG11bHRpdHVkZSBvZiBjbHVzdGVycyBvZiBlYWNoIHR5cGUgY29ycmVzcG9uZCBtb3N0bHkgdG8gaW5kaXZpZHVhbCBhbmltYWxzL3NleGVzLgoKYGBge3J9CnRhYmxlKEZldGNoRGF0YShzdWJ0aXNzQiwgYygnbW91c2UuaWQnLCdpZGVudCcpKSAlPiUgZHJvcGxldmVscygpKQpgYGAKCmBgYHtyfQpwcmV2aW91c19hbm5vdGF0aW9uX3RhYmxlKHN1YnRpc3NCKQpgYGAKCgpgYGB7cn0Kc3ViLmNsdXN0ZXIuaWRzIDwtIGMoMCwgMSwgMikKc3ViLmZyZWVfYW5ub3RhdGlvbiA8LWMoTkEsIE5BLCBOQSkKCnN1Yi5jZWxsX29udG9sb2d5X2NsYXNzIDwtYygiaW1tYXR1cmUgVCBjZWxsIiwgInJlZ3VsYXRvcnkgVCBjZWxsIiwgImltbWF0dXJlIFQgY2VsbCIpCgpzdWJ0aXNzQiA9IHN0YXNoX2Fubm90YXRpb25zKHN1YnRpc3NCLCBzdWIuY2x1c3Rlci5pZHMsIHN1Yi5mcmVlX2Fubm90YXRpb24sIHN1Yi5jZWxsX29udG9sb2d5X2NsYXNzKQp0aXNzID0gc3Rhc2hfc3VidGlzc19pbl90aXNzKHRpc3MsIHN1YnRpc3NCKQpkYXRhLmZyYW1lKHN1Yi5jbHVzdGVyLmlkcywgc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MsIHN1Yi5mcmVlX2Fubm90YXRpb24pCmBgYAoKCiMjIENoZWNraW5nIGZvciBiYXRjaCBlZmZlY3RzCgpDb2xvciBieSBtZXRhZGF0YSwgbGlrZSBwbGF0ZSBiYXJjb2RlLCB0byBjaGVjayBmb3IgYmF0Y2ggZWZmZWN0cy4KYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3NCLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwbGF0ZS5iYXJjb2RlIikKYGBgCgojIEZpbmFsIGNvbG9yaW5nCgpDb2xvciBieSBjZWxsIG9udG9sb2d5IGNsYXNzIG9uIHRoZSBvcmlnaW5hbCBUU05FLgoKYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3NCLCBkby5sYWJlbCA9IFRSVUUsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gImNlbGxfb250b2xvZ3lfY2xhc3MiKQpgYGAKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3Vic2V0IEMgPT0gbGF0ZSBwcm8tQiBjZWxsIChDbHVzdGVyIDgpCgojIyBsYXRlIHByby1CIGNlbGxzIGFyZSByZXBvcnRlZGx5IGNvbW1pdHRlZCB0byBCIGNlbGwgbGluZWFnZSBhcyB0aGV5IGJlZ2luIGV4cHJlc3NpbmcgUGF4NS4gVGhleSBhbHNvIGhhdmUgUmFnMSwgUmFnMiwgYW5kIERudHQgZXhwcmVzc2lvbi4gQXQgc2luZ2xlIGNlbGwgcmVzb2x1dGlvbiB0aGVyZSBzZWVtIHRvIGJlIHR3byBzdWJzZXRzIG9mIGxhdGUgcHJvLUIgY2VsbHM6IERudHQrIGFuZCBEbnR0LS4KCiMjIEl0IGFwcGVhcnMgdGhlcmUgYXJlIG11bHRpcGxlIG5vdmVsIGNlbGwtdHlwZXMgd2l0aGluIHRoZSBQYXg1KyBsYXRlIHByby1CIGNlbGwKCmBgYHtyfQpzdWJ0aXNzQyA9IFN1YnNldERhdGEodGlzcywgaWRlbnQudXNlID0gYyg4KSkKYGBgCgpgYGB7cn0Kc3VidGlzc0MgPC0gc3VidGlzc0MgJT4lIFNjYWxlRGF0YSgpICU+JSAKICBGaW5kVmFyaWFibGVHZW5lcyhkby5wbG90ID0gVFJVRSwgeC5oaWdoLmN1dG9mZiA9IEluZiwgeS5jdXRvZmYgPSAwLjUpICU+JQogIFJ1blBDQShkby5wcmludCA9IEZBTFNFKQpgYGAKCmBgYHtyfQpQQ0hlYXRtYXAob2JqZWN0ID0gc3VidGlzc0MsIHBjLnVzZSA9IDE6MywgY2VsbHMudXNlID0gNTAwLCBkby5iYWxhbmNlZCA9IFRSVUUsIGxhYmVsLmNvbHVtbnMgPSBGQUxTRSwgbnVtLmdlbmVzID0gOCkKUENFbGJvd1Bsb3Qoc3VidGlzc0MpCmBgYAoKCmBgYHtyfQpzdWIubi5wY3MgPSA0CnN1Yi5yZXMudXNlID0gMQpzdWJ0aXNzQyA8LSBzdWJ0aXNzQyAlPiUgRmluZENsdXN0ZXJzKHJlZHVjdGlvbi50eXBlID0gInBjYSIsIGRpbXMudXNlID0gMTpzdWIubi5wY3MsIAogICAgcmVzb2x1dGlvbiA9IHN1Yi5yZXMudXNlLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUpICU+JQogICAgUnVuVFNORShkaW1zLnVzZSA9IDE6c3ViLm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTQyKQoKVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0MsIGRvLmxhYmVsID0gVCwgcHQuc2l6ZSA9IDEuMiwgbGFiZWwuc2l6ZSA9IDQpCgpgYGAKCmBgYHtyfQpwcmV2aW91c19hbm5vdGF0aW9uX3RhYmxlKHN1YnRpc3NDKQpgYGAKQ2hlY2sgZXhwcmVzc2lvbiBvZiBnZW5lcyBvZiBpbnRlcnNldC4KCiMgYGBge3J9CiMgc3VidGlzc0MubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzQywgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCiMgYGBgCiMgCiMgYGBge3J9CiMgc3VidGlzc0MubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDYsIGF2Z19sb2dGQykKIyBgYGAKYGBge3J9CmdlbmVzX3RvX2NoZWNrID0gYygnRG50dCcpCiMgRmVhdHVyZVBsb3Qoc3VidGlzc0MsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSwgbkNvbCA9IDMpCkRvdFBsb3Qoc3VidGlzc0MsIGdlbmVzX3RvX2NoZWNrLCBjb2wubWF4ID0gMi41LCBwbG90LmxlZ2VuZCA9IFQsIGRvLnJldHVybiA9IFQpICsgY29vcmRfZmxpcCgpCgpgYGAKCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MTAyLCBmaWcud2lkdGg9MTV9CmdlbmVzX3RvX2NoZWNrID0gYygnSWw3cicsICdDZDY5JywgJ0x5ejInLCAnVGJ4YTJyJywgJ1ZwcmViMScsICdWcHJlYjInLCAnSWdsbDEnLCAnVnByZWIzJywgJ0NkNzlhJywgJ0NkNzQnLCAnSDItQWEnLCAnSDItQWIxJywgJ0NkNzliJywgJ0gyLUViMScsICdDY25hMicsICdTdG1uMScsICdUb3AyYScsICdNa2k2NycsICdScm0yJywgJ05rZzcnLCAnQ2QxZDEnLCAnRWdyMicsICdDZDE5JywgJ01zNGExJywgJ0NoY2hkMTAnLCAnQ25wJywgJ1JhZzEnLCAnUmFnMicsICdEbnR0JywgJ1BheDUnLCAnSWwycmEnLCAnQ3hjcjUnLCAnQ2NyNicsICdDcjInLCAnQ2QyMicsICdWcHJlYjMnLCAnTWtpNjcnLCAnU3RtbjEnLCAnSWwycmInLCAnQ2RjMjAnLCAnVWJlMmMnLCAnQ2NuYjEnLCAnQ2VucGYnLCAnS3BuYTInLCAnVGNmMycsICdFYmYxJywgJ0lremYxJywgJ1NmcGkxJywgJ1NsY280YTEnLCAnWmZwODEwJywgJ1NrYTEnLCAnS2lmMThhJywgJ0RlcGRjMWInLCAnQnRnMicsICdTMTAwYTgnLCAnU2VyaW5jNScsICdTcm0nLCAnU215ZDInLCAnQ29tdGQxJywgJ0VyZycsICdBcnBwMjEnLCAnTW1ybjEnLCAnS2RtNWInLCAnR3JiNycsICdBY3kzJywgJ1VuZycsICdDeWJiJywgJ0tsaGwxNScsICdFMmYxJywgJ1Ryb2FwJywgJ0VyaTInLCAnTHRiJykKCiMgRmVhdHVyZVBsb3Qoc3VidGlzc0MsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSwgbkNvbCA9IDMpCmBgYAoKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMH0KRG90UGxvdChzdWJ0aXNzQywgdW5pcXVlKGdlbmVzX3RvX2NoZWNrKSwgY29sLm1heCA9IDIuNSwgcGxvdC5sZWdlbmQgPSBULCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQpgYGAKClRoZSBtdWx0aXR1ZGUgb2YgY2x1c3RlcnMgb2YgZWFjaCB0eXBlIGNvcnJlc3BvbmQgbW9zdGx5IHRvIGluZGl2aWR1YWwgYW5pbWFscy9zZXhlcy4KCmBgYHtyfQp0YWJsZShGZXRjaERhdGEoc3VidGlzc0MsIGMoJ21vdXNlLmlkJywnaWRlbnQnKSkgJT4lIGRyb3BsZXZlbHMoKSkKYGBgCgpgYGB7cn0Kc3ViLmNsdXN0ZXIuaWRzIDwtIGMoMCwgMSwgMiwgMywgNCkKc3ViLmZyZWVfYW5ub3RhdGlvbiA8LQogIGMoCiAgIkRudHQtIGxhdGUgcHJvLUIgY2VsbCIsCiAgIkRudHQtIGxhdGUgcHJvLUIgY2VsbCIsCiAgIkRudHQtIGxhdGUgcHJvLUIgY2VsbCIsCiAgIkRudHQrIGxhdGUgcHJvLUIgY2VsbCIsCiAgIkRudHQrIGxhdGUgcHJvLUIgY2VsbCIKICApCiAgCiAgc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MgPC0KICBjKAogICJsYXRlIHByby1CIGNlbGwiLAogICJsYXRlIHByby1CIGNlbGwiLAogICJsYXRlIHByby1CIGNlbGwiLAogICJsYXRlIHByby1CIGNlbGwiLAogICJsYXRlIHByby1CIGNlbGwiCiAgKQogIApzdWJ0aXNzQyA9IHN0YXNoX2Fubm90YXRpb25zKHN1YnRpc3NDLCBzdWIuY2x1c3Rlci5pZHMsIHN1Yi5mcmVlX2Fubm90YXRpb24sIHN1Yi5jZWxsX29udG9sb2d5X2NsYXNzKQp0aXNzID0gc3Rhc2hfc3VidGlzc19pbl90aXNzKHRpc3MsIHN1YnRpc3NDKQpkYXRhLmZyYW1lKHN1Yi5jbHVzdGVyLmlkcywgc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MsIHN1Yi5mcmVlX2Fubm90YXRpb24pCmBgYAoKYGBge3J9CmhlYWQodGlzc0BtZXRhLmRhdGEpCmBgYAoKCiMjIENoZWNraW5nIGZvciBiYXRjaCBlZmZlY3RzCgpDb2xvciBieSBtZXRhZGF0YSwgbGlrZSBwbGF0ZSBiYXJjb2RlLCB0byBjaGVjayBmb3IgYmF0Y2ggZWZmZWN0cy4KYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3NDLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwbGF0ZS5iYXJjb2RlIikKYGBgCgojIyBGaW5hbCBjb2xvcmluZwoKQ29sb3IgYnkgY2VsbCBvbnRvbG9neSBjbGFzcyBvbiB0aGUgb3JpZ2luYWwgVFNORS4KCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzQywgZG8ubGFiZWwgPSBUUlVFLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJmcmVlX2Fubm90YXRpb24iKQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzQywgZG8ubGFiZWwgPSBUUlVFLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJjZWxsX29udG9sb2d5X2NsYXNzIikKYGBgCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3Vic2V0IEQgPT0gaGVtYXRvcG9pZXRpYyBwcmVjdXJzb3IgY2VsbHMgKENsdXN0ZXIgMCkKIyMgVGhpcyBzdWJzZXQgY29udGFpbnMgaGVtYXRvcG9pZXRpYyBtdWx0aXBvdGVudCBwcm9nZW5pdG9yIChNUFApIGNlbGxzIGFuZCBhIHZlcnkgbWludXRlIGZyYWN0aW9uIG9mIEhlbWF0b3BvaWV0aWMgc3RlbSBjZWxscyAoSFNDKS4KCgpgYGB7cn0Kc3VidGlzc0QgPSBTdWJzZXREYXRhKHRpc3MsIGlkZW50LnVzZSA9IGMoMCkpCmBgYAoKYGBge3J9CnN1YnRpc3NEIDwtIHN1YnRpc3NEICU+JSBTY2FsZURhdGEoKSAlPiUgCiAgRmluZFZhcmlhYmxlR2VuZXMoZG8ucGxvdCA9IFRSVUUsIHguaGlnaC5jdXRvZmYgPSBJbmYsIHkuY3V0b2ZmID0gMC41KSAlPiUKICBSdW5QQ0EoZG8ucHJpbnQgPSBGQUxTRSkKYGBgCgpgYGB7cn0KUENIZWF0bWFwKG9iamVjdCA9IHN1YnRpc3NELCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDUwMCwgZG8uYmFsYW5jZWQgPSBUUlVFLCBsYWJlbC5jb2x1bW5zID0gRkFMU0UsIG51bS5nZW5lcyA9IDgpClBDRWxib3dQbG90KHN1YnRpc3NEKQpgYGAKCgpgYGB7cn0Kc3ViLm4ucGNzID0gMjAKc3ViLnJlcy51c2UgPSAxCnN1YnRpc3NEIDwtIHN1YnRpc3NEICU+JSBGaW5kQ2x1c3RlcnMocmVkdWN0aW9uLnR5cGUgPSAicGNhIiwgZGltcy51c2UgPSAxOnN1Yi5uLnBjcywgCiAgICByZXNvbHV0aW9uID0gc3ViLnJlcy51c2UsIHByaW50Lm91dHB1dCA9IDAsIHNhdmUuU05OID0gVFJVRSkgJT4lCiAgICBSdW5UU05FKGRpbXMudXNlID0gMTpzdWIubi5wY3MsIHNlZWQudXNlID0gMTAsIHBlcnBsZXhpdHk9NjUpCgpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzRCwgZG8ubGFiZWwgPSBULCBwdC5zaXplID0gMS4yLCBsYWJlbC5zaXplID0gNCkKYGBgCgpgYGB7cn0KcHJldmlvdXNfYW5ub3RhdGlvbl90YWJsZShzdWJ0aXNzRCkKYGBgCgoKQ2hlY2sgZXhwcmVzc2lvbiBvZiBnZW5lcyBvZiBpbnRlcnNldC4KCiMgYGBge3J9CiMgc3VidGlzc0QubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzRCwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCiMgYGBgCiMgCiMgYGBge3J9CiMgc3VidGlzc0QubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDYsIGF2Z19sb2dGQykKIyBgYGAKCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MTIwLCBmaWcud2lkdGg9MTV9CmdlbmVzX3RvX2NoZWNrID0gc29ydCh1bmlxdWUoYygnSWw3cicsICdLaXQnLCAnQXR4bjEnLCAnQ2QzNCcsICdTbGFtZjEnLCAnRmx0MycsICdDZDYzJywgJ015bDEyYicsICdNdWMxMycsICdTZHNsJywgJ1N0YXQzJywgJ1d0YXAnLCAnTXBsJywgJ1R4bmlwJywgJ0x0YicsICdQZHprMWlwMScsICdFc2FtJywgJ0Npc2gnLCAnVHltcycsICdUazEnLCAnMjgxMDQxN0gxM1JpaycsICdScm0yJywgJ1VocmYxJywgJ1R1YmExYicsICdNeWwxMCcsICdKdW5iJywgJ0ZvcycsICdJZXIyJywgJ0R1c3AxJywgJ0x5NmEnLCAnVWJlMmMnLCAnQ2NuYjInLCAnQ2NuYjEnLCAnQ2RjMjAnLCAnQ2NuYTInLCAnRmx0MycsICdEbnR0JywgJ0dtMTE0MjgnLCAnTmNmMScsICdNbjEnLCAnSDItT2InLCAnQ3RzZycsICdDY2w5JywgJ1NlbGwnLCAnSGszJywgJ0NkNDgnLCAnR2F0YTEnLCAnTWZzZDJiJywgJ1R1YmE4JywgJ0l0Z2EyYicsICdBcG9lJywgJ1BmNCcsICdFbGFuZScsICdNczRhMycsICdDdHNnJywgJ01wbycsICdQcnRuMycsICdDZDY5JywgJ0NjcjcnLCAnQ3RsYTJhJywgJ1R5cm9icCcsICdTZXJwaW5iOScsICdMeXoyJywgJ0hwJywgJ0x5NmMyJywgJ0NkNzQnLCAnSDItQWEnLCAnSDItQWIxJywgJ0NkNzliJywgJ0gyLUViMScsICdDY25hMicsICdUb3AyYScsICdScm0yJywgJ05rZzcnLCAnQ2QxZDEnLCAnQ2hjaGQxMCcsICdDbnAnLCAnUmFnMicsICdEbnR0JywgJ01raTY3JywgJ1N0bW4xJywgJ0dpbWFwOCcsICdKaGRtMWQnLCAnS2lmMTEnLCAnU3BhZzUnLCAnWGlzdCcsICdUc2l4JywgJ05vdGNoMicsICdTbGMzOWExJywgJ1NvY3MzJywgJ1ZsZGxyJywgJ01jbTQnLCAnVW5nJykpKQoKIyAjIEZlYXR1cmVQbG90KHN1YnRpc3NELCBnZW5lc190b19jaGVjaywgcHQuc2l6ZSA9IDEsIG5Db2wgPSAzKQoKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQojIERvdFBsb3Qoc3VidGlzc0QsIGdlbmVzX3RvX2NoZWNrLCBjb2wubWF4ID0gMi41LCBwbG90LmxlZ2VuZCA9IFQsIGRvLnJldHVybiA9IFQpICsgY29vcmRfZmxpcCgpCmBgYAoKClRoZSBtdWx0aXR1ZGUgb2YgY2x1c3RlcnMgb2YgZWFjaCB0eXBlIGNvcnJlc3BvbmQgbW9zdGx5IHRvIGluZGl2aWR1YWwgYW5pbWFscy9zZXhlcy4KCmBgYHtyfQp0YWJsZShGZXRjaERhdGEoc3VidGlzc0QsIGMoJ21vdXNlLmlkJywnaWRlbnQnKSkgJT4lIGRyb3BsZXZlbHMoKSkKYGBgCgpgYGB7cn0Kc3ViLmNsdXN0ZXIuaWRzIDwtIGMoMCwgMSwgMiwgMywgNCwgNSwgNikKc3ViLmZyZWVfYW5ub3RhdGlvbiA8LSBjKE5BLCBOQSwgTkEsIE5BLCBOQSwgTkEsIE5BKQpzdWIuY2VsbF9vbnRvbG9neV9jbGFzcyA8LSBjKAogICJTbGFtZjEtbmVnYXRpdmUgbXVsdGlwb3RlbnQgcHJvZ2VuaXRvciBjZWxsIiwKICAiaGVtYXRvcG9pZXRpYyBwcmVjdXJzb3IgY2VsbCIsCiAgIlNsYW1mMS1uZWdhdGl2ZSBtdWx0aXBvdGVudCBwcm9nZW5pdG9yIGNlbGwiLAogICJjb21tb24gbHltcGhvaWQgcHJvZ2VuaXRvciIsCiAgIlNsYW1mMS1wb3NpdGl2ZSBtdWx0aXBvdGVudCBwcm9nZW5pdG9yIGNlbGwiLAogICJncmFudWxvY3l0ZSBtb25vY3l0ZSBwcm9nZW5pdG9yIGNlbGwiLAogICJtZWdha2FyeW9jeXRlLWVyeXRocm9pZCBwcm9nZW5pdG9yIGNlbGwiCiAgKQoKc3VidGlzc0QgPSBzdGFzaF9hbm5vdGF0aW9ucyhzdWJ0aXNzRCwgc3ViLmNsdXN0ZXIuaWRzLCBzdWIuZnJlZV9hbm5vdGF0aW9uLCBzdWIuY2VsbF9vbnRvbG9neV9jbGFzcykKdGlzcyA9IHN0YXNoX3N1YnRpc3NfaW5fdGlzcyh0aXNzLCBzdWJ0aXNzRCkKaGVhZCh0aXNzQG1ldGEuZGF0YSkKZGF0YS5mcmFtZShzdWIuY2x1c3Rlci5pZHMsIHN1Yi5jZWxsX29udG9sb2d5X2NsYXNzLCBzdWIuZnJlZV9hbm5vdGF0aW9uKQpgYGAKCmBgYHtyfQpoZWFkKHN1YnRpc3NEQG1ldGEuZGF0YSkKYGBgCgoKIyMgQ2hlY2tpbmcgZm9yIGJhdGNoIGVmZmVjdHMKCkNvbG9yIGJ5IG1ldGFkYXRhLCBsaWtlIHBsYXRlIGJhcmNvZGUsIHRvIGNoZWNrIGZvciBiYXRjaCBlZmZlY3RzLgpgYGB7cn0KVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0QsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gInBsYXRlLmJhcmNvZGUiKQpgYGAKCiMjIEZpbmFsIGNvbG9yaW5nCgpDb2xvciBieSBjZWxsIG9udG9sb2d5IGNsYXNzIG9uIHRoZSBvcmlnaW5hbCBUU05FLgoKYGBge3J9CiMgVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0QsIGRvLmxhYmVsID0gVFJVRSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiZnJlZV9hbm5vdGF0aW9uIikKVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0QsIGRvLmxhYmVsID0gVFJVRSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiY2VsbF9vbnRvbG9neV9jbGFzcyIpCmBgYAoKCgojIyBGaW5hbCBjb2xvcmluZwoKQ29sb3IgYnkgY2VsbCBvbnRvbG9neSBjbGFzcyBvbiB0aGUgb3JpZ2luYWwgVFNORS4KCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSB0aXNzLCBkby5sYWJlbCA9IFRSVUUsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gImZyZWVfYW5ub3RhdGlvbiIpClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLmxhYmVsID0gVFJVRSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiY2VsbF9vbnRvbG9neV9jbGFzcyIpCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMjIFN1YmNsdXN0ZXIgdGhlIGNsdXN0ZXJzIDcgb2YgdGlzcwoKIyBTdWJzZXQgRSA9PSAgZ3JhbnVsb2N5dGUgbW9ub2N5dGUgcHJvZ2VuaXRvciBjZWxsLCBtb25vY3l0ZQoKYGBge3J9CnN1YnRpc3NFID0gU3Vic2V0RGF0YSh0aXNzLCBpZGVudC51c2UgPSBjKDcpKQpgYGAKCmBgYHtyfQpzdWJ0aXNzRSA8LSBzdWJ0aXNzRSAlPiUgU2NhbGVEYXRhKCkgJT4lIAogIEZpbmRWYXJpYWJsZUdlbmVzKGRvLnBsb3QgPSBUUlVFLCB4LmhpZ2guY3V0b2ZmID0gSW5mLCB5LmN1dG9mZiA9IDAuNSkgJT4lCiAgUnVuUENBKGRvLnByaW50ID0gRkFMU0UpCmBgYAoKYGBge3J9ClBDSGVhdG1hcChvYmplY3QgPSBzdWJ0aXNzRSwgcGMudXNlID0gMTozLCBjZWxscy51c2UgPSAxNzAsIGRvLmJhbGFuY2VkID0gVFJVRSwgbGFiZWwuY29sdW1ucyA9IEZBTFNFLCBudW0uZ2VuZXMgPSA4KQpQQ0VsYm93UGxvdChzdWJ0aXNzRSkKYGBgCgoKYGBge3J9CnN1Yi5uLnBjcyA9IDIwCnN1Yi5yZXMudXNlID0gMQpzdWJ0aXNzRSA8LSBzdWJ0aXNzRSAlPiUgRmluZENsdXN0ZXJzKHJlZHVjdGlvbi50eXBlID0gInBjYSIsIGRpbXMudXNlID0gMTpzdWIubi5wY3MsIAogICAgcmVzb2x1dGlvbiA9IHN1Yi5yZXMudXNlLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUsIGZvcmNlPVRSVUUpICU+JQogICAgUnVuVFNORShkaW1zLnVzZSA9IDE6c3ViLm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTYwKQoKVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzc0UsIGRvLmxhYmVsID0gVCwgcHQuc2l6ZSA9IDEuMiwgbGFiZWwuc2l6ZSA9IDQpCgpgYGAKCmBgYHtyfQpwcmV2aW91c19hbm5vdGF0aW9uX3RhYmxlKHN1YnRpc3NFKQpgYGAKCgpDaGVjayBleHByZXNzaW9uIG9mIGdlbmVzIG9mIGludGVyc2V0LgoKCiMgYGBge3J9CiMgc3VidGlzc0UubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzRSwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCiMgYGBgCiMgCiMgYGBge3J9CiMgc3VidGlzc0UubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDYsIGF2Z19sb2dGQykKIyBgYGAKCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MTM4LCBmaWcud2lkdGg9MTV9CmdlbmVzX3RvX2NoZWNrID0gYygnSG94YjUnLCAnVHJpYjMnLCAnTmVvMScsICdJbDdyJywgJ0tpdCcsICdBdHhuMScsICdDZDM0JywgJ1NsYW1mMScsICdGbHQzJywgJ0NkNjMnLCAnTXlsMTJiJywgJ011YzEzJywgJ1Nkc2wnLCAnU3RhdDMnLCAnV3RhcCcsICdNcGwnLCAnVHhuaXAnLCAnTHRiJywgJ1BkemsxaXAxJywgJ0VzYW0nLCAnQ2lzaCcsICdUeW1zJywgJ1RrMScsICcyODEwNDE3SDEzUmlrJywgJ1JybTInLCAnVWhyZjEnLCAnVHViYTFiJywgJ015bDEwJywgJ0p1bmInLCAnRm9zJywgJ0llcjInLCAnRHVzcDEnLCAnTHk2YScsICdVYmUyYycsICdDY25iMicsICdDY25iMScsICdDZGMyMCcsICdDY25hMicsICdEbnR0JywgJ0dtMTE0MjgnLCAnTmNmMScsICdNbjEnLCAnSDItT2InLCAnQ3RzZycsICdNcG8nLCAnQ2NsOScsICdTZWxsJywgJ0hrMycsICdDZDQ4JywgJ0dhdGExJywgJ01mc2QyYicsICdUdWJhOCcsICdJdGdhMmInLCAnQXBvZScsICdQZjQnLCAnRWxhbmUnLCAnTXM0YTMnLCAnQ3RzZycsICdQcnRuMycsICdDZDY5JywgJ0NjcjcnLCAnQ3RsYTJhJywgJ1R5cm9icCcsICdTZXJwaW5iOScsICdMeXoyJywgJ0hwJywgJ0x5NmMyJywgJ0NkNzQnLCAnSDItQWEnLCAnSDItQWIxJywgJ0NkNzliJywgJ0gyLUViMScsICdDY25hMicsICdUb3AyYScsICdOa2c3JywgJ0NkMWQxJywgJ0NoY2hkMTAnLCAnQ25wJywgJ1JhZzEnLCAgJ1JhZzInLCAnRG50dCcsICdNa2k2NycsICdTdG1uMScsICdHaW1hcDgnLCAnSmhkbTFkJywgJ0tpZjExJywgJ1NwYWc1JywgJ1hpc3QnLCAnVHNpeCcsICdOb3RjaDInLCAnU2xjMzlhMScsICdTb2NzMycsICdWbGRscicsICdNY200JywgJ1VuZycsICdGYW0xMDJhJywgJ0NjbDQnLCAnUHl5JywgJ0FrNCcsICAnUHJjMScsICdDZW5wZicsICdQcnIxMScsICdMaGNncicsICdUZ20yJywgJ0FiY2czJywgJ0NjbmUyJywgJ1Bhc2snLCAnTnNnMScsICdCb2snLCAnS2xmMScsICdUcmVtbDEnKQoKIyBGZWF0dXJlUGxvdChzdWJ0aXNzRSwgZ2VuZXNfdG9fY2hlY2ssIHB0LnNpemUgPSAxLCBuQ29sID0gMykKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQojRG90UGxvdChzdWJ0aXNzRSwgZ2VuZXNfdG9fY2hlY2ssIGNvbC5tYXggPSAyLjUsIHBsb3QubGVnZW5kID0gVCwgZG8ucmV0dXJuID0gVCkgKyBjb29yZF9mbGlwKCkKYGBgCgpUaGUgbXVsdGl0dWRlIG9mIGNsdXN0ZXJzIG9mIGVhY2ggdHlwZSBjb3JyZXNwb25kIG1vc3RseSB0byBpbmRpdmlkdWFsIGFuaW1hbHMvc2V4ZXMuCgpgYGB7cn0KdGFibGUoRmV0Y2hEYXRhKHN1YnRpc3NFLCBjKCdtb3VzZS5pZCcsJ2lkZW50JykpICU+JSBkcm9wbGV2ZWxzKCkpCmBgYAoKYGBge3J9CnN1Yi5jbHVzdGVyLmlkcyA8LSBjKDAsIDEsIDIsIDMpCnN1Yi5mcmVlX2Fubm90YXRpb24gPC0gYygKICBOQSwgTkEsIE5BLCBOQQogICkKc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MgPC0KICBjKAogICJtb25vY3l0ZSIsCiAgIm1vbm9jeXRlIiwKICAibW9ub2N5dGUiLAogICJncmFudWxvY3l0ZSBtb25vY3l0ZSBwcm9nZW5pdG9yIGNlbGwiCiAgKQoKc3VidGlzc0UgPSBzdGFzaF9hbm5vdGF0aW9ucyhzdWJ0aXNzRSwgc3ViLmNsdXN0ZXIuaWRzLCBzdWIuZnJlZV9hbm5vdGF0aW9uLCBzdWIuY2VsbF9vbnRvbG9neV9jbGFzcykKdGlzcyA9IHN0YXNoX3N1YnRpc3NfaW5fdGlzcyh0aXNzLCBzdWJ0aXNzRSkKCmBgYAoKYGBge3J9CmhlYWQodGlzc0BtZXRhLmRhdGEpCmBgYAoKCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKQ29sb3IgYnkgbWV0YWRhdGEsIGxpa2UgcGxhdGUgYmFyY29kZSwgdG8gY2hlY2sgZm9yIGJhdGNoIGVmZmVjdHMuCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzRSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAicGxhdGUuYmFyY29kZSIpCmBgYAoKIyMgRmluYWwgY29sb3JpbmcKCkNvbG9yIGJ5IGNlbGwgb250b2xvZ3kgY2xhc3Mgb24gdGhlIG9yaWdpbmFsIFRTTkUuCgpgYGB7cn0KIyBUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzRSwgZG8ubGFiZWwgPSBUUlVFLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJmcmVlX2Fubm90YXRpb24iKQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzRSwgZG8ubGFiZWwgPSBUUlVFLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJjZWxsX29udG9sb2d5X2NsYXNzIikKYGBgCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBGaW5hbCBjb2xvcmluZyAtIGVudGlyZSB0aXNzdWUhCgpDb2xvciBieSBjZWxsIG9udG9sb2d5IGNsYXNzIG9uIHRoZSBvcmlnaW5hbCBUU05FLgoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTR9ClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLmxhYmVsID0gVFJVRSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiZnJlZV9hbm5vdGF0aW9uIikKVFNORVBsb3Qob2JqZWN0ID0gdGlzcywgZG8ubGFiZWwgPSBUUlVFLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJjZWxsX29udG9sb2d5X2NsYXNzIikKYGBgCgojIFNhdmUgdGhlIFJvYmplY3QgZm9yIGxhdGVyCgpgYGB7cn0KZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICcwNF90aXNzdWVfcm9ial9nZW5lcmF0ZWQnLCAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJmYWNzXyIsIHRpc3N1ZV9vZl9pbnRlcmVzdCwgIl9zZXVyYXRfdGlzcy5Sb2JqIikpCnByaW50KGZpbGVuYW1lKQpzYXZlKHRpc3MsIGZpbGU9ZmlsZW5hbWUpCmBgYAoKYGBge3J9CiMgVG8gcmVsb2FkIGEgc2F2ZWQgb2JqZWN0CiMgZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICcwNF90aXNzdWVfcm9ial9nZW5lcmF0ZWQnLCAKIyAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoImZhY3MiLCB0aXNzdWVfb2ZfaW50ZXJlc3QsICJfc2V1cmF0X3Rpc3MuUm9iaiIpKQojIGxvYWQoZmlsZT1maWxlbmFtZSkKYGBgCgoKIyBFeHBvcnQgdGhlIGZpbmFsIG1ldGFkYXRhCgoKCgpXcml0ZSB0aGUgY2VsbCBvbnRvbG9neSBhbmQgZnJlZSBhbm5vdGF0aW9ucyB0byBDU1YuCgpgYGB7cn0Kc2F2ZV9hbm5vdGF0aW9uX2Nzdih0aXNzLCB0aXNzdWVfb2ZfaW50ZXJlc3QsICJmYWNzIikKYGBgCg==